package org.qing.cloud.commons.logs.log4j2;

import org.slf4j.MDC;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.GenericApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;

public class Log4j2StartedEventListener implements GenericApplicationListener {
	public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 10;

	private static Class<?>[] EVENT_TYPES = { 
			ApplicationStartingEvent.class, 
			ApplicationEnvironmentPreparedEvent.class,
			ApplicationPreparedEvent.class, 
			ContextClosedEvent.class, 
			ApplicationFailedEvent.class };

	private static Class<?>[] SOURCE_TYPES = { 
			SpringApplication.class, 
			ApplicationContext.class };

	@Override
	@SuppressWarnings("preview")
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationEnvironmentPreparedEvent preparedEvent) {
			Environment env = preparedEvent.getEnvironment();
			String driver = env.getProperty("logging.driver");
			System.out.println(String.format("logging.driver=[%s]", driver));
			if (StringUtils.isEmpty(driver)) {
				return;
			}
			String minSize = env.getProperty("logging.log4j2.minSize");
			System.out.println(String.format("logging.log4j2.minSize=[%s]", minSize));
			MDC.put("LOGGING_LOG4J2_MINSIZE", minSize);
			String maxSize = env.getProperty("logging.log4j2.maxSize");
			System.out.println(String.format("logging.log4j2.maxSize=[%s]", maxSize));
			MDC.put("LOGGING_LOG4J2_MAXSIZE", maxSize);
			String maxHistory = env.getProperty("logging.log4j2.maxHistory");
			System.out.println(String.format("logging.log4j2.maxHistory=[%s]", maxHistory));
			MDC.put("LOGGING_LOG4J2_MAXHISTORY", maxHistory);
			String maxMumber = env.getProperty("logging.log4j2.maxMumber");
			System.out.println(String.format("logging.log4j2.maxMumber=[%s]", maxMumber));
			MDC.put("LOGGING_LOG4J2_MAXMUMBER", maxMumber);
			String path = env.getProperty("logging.log4j2.path");
			System.out.println(String.format("logging.log4j2.path=[%s]", path));
			MDC.put("LOGGING_LOG4J2_PATH", path);
			String moduleName = env.getProperty("logging.log4j2.moduleName");
			System.out.println(String.format("logging.log4j2.moduleName=[%s]", moduleName));
			MDC.put("LOGGING_LOG4J2_MODULENAME", moduleName);
			String level = env.getProperty("logging.log4j2.level");
			System.out.println(String.format("logging.log4j2.level=[%s]", level));
			MDC.put("LOGGING_LOG4J2_LEVEL", level);
		}
	}

	@Override
	public int getOrder() {
		return DEFAULT_ORDER;
	}

	@Override
	public boolean supportsEventType(ResolvableType resolvableType) {
		return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
	}

	@Override
	public boolean supportsSourceType(Class<?> sourceType) {
		return isAssignableFrom(sourceType, SOURCE_TYPES);
	}

	private boolean isAssignableFrom(Class<?> type, Class<?>... supportedTypes) {
		if (type != null) {
			for (Class<?> supportedType : supportedTypes) {
				if (supportedType.isAssignableFrom(type)) {
					return true;
				}
			}
		}
		return false;
	}
}
